/*
 ***************************************************************************************
 * EP for web developers.Supported By Junxworks
 * @Title:  Config.java   
 * @Package io.github.junxworks.ep.seed.config   
 * @Description: (用一句话描述该文件做什么)   
 * @author: Administrator
 * @date:   2021-2-28 17:19:39   
 * @version V1.0 
 * @Copyright: 2021 Junxworks. All rights reserved. 
 * 注意：
 *  ---------------------------------------------------------------------------------- 
 * 文件修改记录
 *     文件版本：         修改人：             修改原因：
 ***************************************************************************************
 */
package io.github.junxworks.qt.config;

import org.apache.shiro.cache.CacheManager;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import io.github.junxworks.ep.auth.cache.EPShiroMemCacheManager;
import io.github.junxworks.ep.qlexp.RuleEngine;
import io.github.junxworks.ep.qlexp.RuleEngineBuilder;
import io.github.junxworks.ep.qlexp.functions.ClassFunctionDefinition;
import io.github.junxworks.junx.core.executor.RejectedExecutionHandlers;
import io.github.junxworks.junx.core.executor.StandardThreadExecutor;
import io.github.junxworks.junx.event.EventBus;
import io.github.junxworks.junx.event.EventChannel;
import io.github.junxworks.junx.event.impl.DisruptorEventChannel;
import io.github.junxworks.junx.event.impl.SimpleEventBus;
import io.github.junxworks.junx.event.impl.SimpleEventChannel;
import io.github.junxworks.qt.modules.data.handler.DataStoreHandler;
import io.github.junxworks.qt.modules.mm.engine.handlers.ExpressionHandler;
import io.github.junxworks.qt.modules.mm.engine.handlers.FieldInitHandler;
import io.github.junxworks.qt.modules.mm.engine.handlers.ModelHandler;
import io.github.junxworks.qt.modules.mm.engine.handlers.StatHandler;

@Configuration
@EnableConfigurationProperties({ QtConfig.class })
public class Beans {

	/**
	 * 注入shiro缓存管理，这里默认开发环境为本地内存
	 * EP框架默认是redis缓存，如果是测试环境或者是生产环境，不用配置这个bean
	 *
	 * @return the cache manager
	 */
	@Bean
	public CacheManager epShiroMemCacheManager() {
		return new EPShiroMemCacheManager();
	}

	@Primary
	@Bean(initMethod = "start", destroyMethod = "stop")
	public StandardThreadExecutor globalExecutor(QtConfig config) {
		StandardThreadExecutor executor = new StandardThreadExecutor();
		config.getExecutor().setRejectedExecutionHandler(RejectedExecutionHandlers.CallerRuns.name());
		executor.setConfig(config.getExecutor());
		return executor;
	}

	@Bean(name = "dataStoreExecutor", initMethod = "start", destroyMethod = "stop")
	public StandardThreadExecutor dataStoreExecutor() {
		StandardThreadExecutor executor = new StandardThreadExecutor();
		executor.getConfig().setRejectedExecutionHandler(RejectedExecutionHandlers.CallerRuns.name());
		executor.getConfig().setMaxThreads(5);
		executor.getConfig().setMinSpareThreads(1);
		return executor;
	}

	@Bean
	public RuleEngine ruleEngine() throws Exception {
		return new RuleEngineBuilder().addFunction(new ClassFunctionDefinition("数据流", "io.github.junxworks.qt.modules.mm.engine.functions.Functions", "getDatastream", new Class<?>[] { String.class }, new String[] { "数据源名称" }, null, null))
				.addFunction(new ClassFunctionDefinition("指标", "io.github.junxworks.qt.modules.mm.engine.functions.Functions", "getStat", new Class<?>[] { String.class }, new String[] { "指标名称" }, null, null))
				.addFunction(new ClassFunctionDefinition("表达式", "io.github.junxworks.qt.modules.mm.engine.functions.Functions", "getExpRes", new Class<?>[] { String.class }, new String[] { "表达式名称" }, null, null))
				.addFunction(new ClassFunctionDefinition("趋势", "io.github.junxworks.qt.modules.mm.engine.functions.Functions", "linearRegression", new Class<?>[] { Object[].class }, new String[] { "double数组" }, null, null))
				.addFunction(new ClassFunctionDefinition("行业", "io.github.junxworks.qt.modules.mm.engine.functions.Functions", "industry", new Class<?>[] {}, new String[] {}, null, null)).build();
	}

	@Bean(initMethod = "start", destroyMethod = "stop")
	public EventBus eventBus() {
		SimpleEventBus bus = new SimpleEventBus();
		bus.setName("qt-event-bus");
		return bus;
	}

	@Bean
	public DataStoreHandler tushareDataStoreHandler() {
		return new DataStoreHandler();
	}

	@Bean
	public DataStoreHandler statResultStoreHandler() {
		DataStoreHandler ds = new DataStoreHandler();
		ds.setBatchSize(512);
		return ds;
	}

	@Bean
	public DataStoreHandler expResultStoreHandler() {
		return new DataStoreHandler();
	}

	@Bean
	public DataStoreHandler modelResultStoreHandler() {
		return new DataStoreHandler();
	}

	@Bean
	public EventChannel storeDataChannel(EventBus eventBus, DataStoreHandler tushareDataStoreHandler) {
		DisruptorEventChannel channel = new DisruptorEventChannel("Data-Store-Channel", Topics.STORE_DATA);
		channel.setEventHandler(tushareDataStoreHandler);
		eventBus.registerChannel(channel);
		return channel;
	}

	@Bean
	public EventChannel storeStatResultChannel(EventBus eventBus, DataStoreHandler statResultStoreHandler) {
		DisruptorEventChannel channel = new DisruptorEventChannel("Stat-Store-Channel", Topics.STORE_STAT_RES);
		channel.setEventHandler(statResultStoreHandler);
		eventBus.registerChannel(channel);
		return channel;
	}

	@Bean
	public EventChannel storeExpResultChannel(EventBus eventBus, DataStoreHandler expResultStoreHandler) {
		DisruptorEventChannel channel = new DisruptorEventChannel("Exp-Store-Channel", Topics.STORE_EXP_RES);
		channel.setEventHandler(expResultStoreHandler);
		eventBus.registerChannel(channel);
		return channel;
	}

	@Bean
	public EventChannel storeModelResultChannel(EventBus eventBus, DataStoreHandler modelResultStoreHandler) {
		DisruptorEventChannel channel = new DisruptorEventChannel("Model-Store-Channel", Topics.STORE_MODEL_RES);
		channel.setEventHandler(modelResultStoreHandler);
		eventBus.registerChannel(channel);
		return channel;
	}

	@Bean
	public EventChannel fieldInitChannel(EventBus eventBus, FieldInitHandler handler) {
		SimpleEventChannel channel = new SimpleEventChannel("Field-Init-Channel", Topics.FIELD_INIT);
		channel.setEventHandler(handler);
		eventBus.registerChannel(channel);
		return channel;
	}

	@Bean
	public EventChannel statSyncChannel(EventBus eventBus, StatHandler handler) {
		SimpleEventChannel channel = new SimpleEventChannel("Stat-sync-Channel", Topics.STAT_SYNC);
		channel.setEventHandler(handler);
		eventBus.registerChannel(channel);
		return channel;
	}

	@Bean
	public EventChannel statAsyncChannel(EventBus eventBus, StatHandler handler) {
		SimpleEventChannel channel = new SimpleEventChannel("Stat-async-Channel", Topics.STAT_ASYNC);
		channel.setEventHandler(handler);
		eventBus.registerChannel(channel);
		return channel;
	}

	@Bean
	public EventChannel expressionChannel(EventBus eventBus, ExpressionHandler handler) {
		SimpleEventChannel channel = new SimpleEventChannel("Expression-Channel", Topics.EXPRESSION);
		channel.setEventHandler(handler);
		eventBus.registerChannel(channel);
		return channel;
	}

	@Bean
	public EventChannel modelChannel(EventBus eventBus, ModelHandler handler) {
		SimpleEventChannel channel = new SimpleEventChannel("Model-Channel", Topics.MODEL);
		channel.setEventHandler(handler);
		eventBus.registerChannel(channel);
		return channel;
	}
}
